package cn.golxen.rsms.service.impl;

import cn.golxen.rsms.bean.bo.AddOrOutGoodsNumBo;
import cn.golxen.rsms.bean.bo.BusinessDateBo;
import cn.golxen.rsms.bean.bo.CustomerConsumedStoresBo;
import cn.golxen.rsms.bean.bo.CustomerPurchasedGoodsBo;
import cn.golxen.rsms.bean.entity.CustomerMain;
import cn.golxen.rsms.bean.vo.CustomerNewAndOldVo;
import cn.golxen.rsms.commons.utils.LocalDateTimeUtils;
import cn.golxen.rsms.mapper.CustomerMapper;
import cn.golxen.rsms.service.CustomerService;
import cn.golxen.rsms.service.StoreService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.util.*;

@Slf4j
@Service
public class CustomerServiceImpl implements CustomerService {

    @Autowired
    StoreService storeService;
    @Autowired
    CustomerMapper customerMapper;
    @Override
    public int customerPayHandle(String customerId, int storeId, List<AddOrOutGoodsNumBo> goodsDetailObject) {
        Set<String> customerSet=storeService.getCustomer(storeId);
        if (customerSet==null)
            customerSet=new HashSet<>();
        customerSet.add(customerId);
        storeService.updateCustomer(storeId,customerSet);
        CustomerMain customerMain=getCustomerMain(customerId);

        if (customerMain!=null){
            CustomerMain customerMain1=customerMainHandel(customerMain,storeId,goodsDetailObject);
            return updateCustomerMain(customerMain1);
        }else {
            customerMain=new CustomerMain();
            customerMain.setCustomerId(customerId);
            customerMain.setPurchasedGoodsObj(new HashMap<>());
            customerMain.setConsumedStoresObj(new HashMap<>());
            CustomerMain customerMain1=customerMainHandel(customerMain,storeId,goodsDetailObject);
            return addCustomerMain(customerMain1);
        }

    }

    @Override
    public CustomerMain getCustomerMain(String customerId) {
        CustomerMain customerMain=customerMapper.getCustomerMain(customerId);
        if (customerMain!=null){
            Map<Integer,CustomerConsumedStoresBo> storesBoMap=(new HashMap<Integer,CustomerConsumedStoresBo>(JSONObject.parseObject(customerMain.getConsumedStoresStr(), Map.class)));
            Map<String,CustomerPurchasedGoodsBo> goodsBoMap=(new HashMap<String,CustomerPurchasedGoodsBo>(JSONObject.parseObject(customerMain.getPurchasedGoodsStr(), Map.class)));
            customerMain.setConsumedStoresObj(storesBoMap);
            customerMain.setPurchasedGoodsObj(goodsBoMap);
        }


        return customerMain;
    }

    @Override
    public List<CustomerMain> getCustomerMainList(Set<String> customerIdSet) {
        List<CustomerMain> customerMainList=customerMapper.getCustomerMainList(customerIdSet);

        return jsonToObject(customerMainList);
    }

    @Override
    public int updateCustomerMain(CustomerMain customerMain) {
        customerMain.setPurchasedGoodsStr(JSONObject.toJSONString(customerMain.getPurchasedGoodsObj()));
        customerMain.setConsumedStoresStr(JSONObject.toJSONString(customerMain.getConsumedStoresObj()));
        return customerMapper.updateCustomerMain(customerMain);
    }

    @Override
    public int addCustomerMain(CustomerMain customerMain) {
        customerMain.setPurchasedGoodsStr(JSONObject.toJSONString(customerMain.getPurchasedGoodsObj()));
        customerMain.setConsumedStoresStr(JSONObject.toJSONString(customerMain.getConsumedStoresObj()));
        return customerMapper.addCustomerMain(customerMain);
    }

    @Override
    public CustomerNewAndOldVo getCustomerNewAndOldVo(BusinessDateBo bo) {
        List<CustomerMain> customerMainList=customerMapper.getCustomerMainByPeriod(bo);
        jsonToObject(customerMainList);
        CustomerNewAndOldVo vo=new CustomerNewAndOldVo();
        vo.setNewCustomerList(new ArrayList<>());
        vo.setOldCustomerList(new ArrayList<>());
        for (CustomerMain customerMain:customerMainList){
            CustomerConsumedStoresBo storesBo=customerMain.getConsumedStoresObj().get(bo.getStoreId());
            LocalDateTime firstDate=storesBo.getFirstDate();
            if (firstDate.equals(bo.getStartDate())||firstDate.isAfter(bo.getStartDate())&&firstDate.isBefore(bo.getEndDate())){
                vo.getNewCustomerList().add(customerMain);
            }else {
                vo.getOldCustomerList().add(customerMain);
            }
        }
        vo.setNewNum(vo.getNewCustomerList().size());
        vo.setOldNum(vo.getOldCustomerList().size());
        return vo;
    }

    private CustomerMain customerMainHandel(CustomerMain customerMain,int storeId, List<AddOrOutGoodsNumBo> goodsDetailObject){
        DecimalFormat df = new DecimalFormat("#.00");
        LocalDateTime nowTime=LocalDateTimeUtils.getLocalDateTime();
        Map<Integer, CustomerConsumedStoresBo> consumedStoresObj=customerMain.getConsumedStoresObj();
        Map<String, CustomerPurchasedGoodsBo> purchasedGoodsObj=customerMain.getPurchasedGoodsObj();
        CustomerConsumedStoresBo storesBo=JSONObject.parseObject(JSONObject.toJSONString(consumedStoresObj.get(storeId)),CustomerConsumedStoresBo.class);
        if (storesBo!=null){
            storesBo.setLastDate(nowTime);
            storesBo.setTimes(storesBo.getTimes()+1);
        }else {
            storesBo=new CustomerConsumedStoresBo();
            storesBo.setLastDate(nowTime);
            storesBo.setTimes(1);
            storesBo.setFirstDate(nowTime);
        }
        consumedStoresObj.put(storeId,storesBo);
        customerMain.setConsumedStoresObj(consumedStoresObj);

        for (AddOrOutGoodsNumBo addOrOutGoodsNumBo:goodsDetailObject){
            if (addOrOutGoodsNumBo.getCode().length()!=13)
                continue;
            CustomerPurchasedGoodsBo goodsBo=JSONObject.parseObject(JSONObject.toJSONString(purchasedGoodsObj.get(addOrOutGoodsNumBo.getCode())),CustomerPurchasedGoodsBo.class);
            if (goodsBo!=null){
                goodsBo.setTimes(goodsBo.getTimes()+1);
                goodsBo.setNum(goodsBo.getNum()+addOrOutGoodsNumBo.getNum());
                goodsBo.setTotal(Double.valueOf(df.format(goodsBo.getTotal()+addOrOutGoodsNumBo.getNum()*addOrOutGoodsNumBo.getPrice())));
                if (!goodsBo.getStoreIdStr().contains(String.valueOf(storeId)))
                    goodsBo.setStoreIdStr(goodsBo.getStoreIdStr()+"|"+storeId);
            }else {
                goodsBo=new CustomerPurchasedGoodsBo();
                goodsBo.setTimes(1);
                goodsBo.setNum(addOrOutGoodsNumBo.getNum());
                goodsBo.setTotal(Double.valueOf(df.format(addOrOutGoodsNumBo.getNum()*addOrOutGoodsNumBo.getPrice())));
                goodsBo.setStoreIdStr(String.valueOf(storeId));
            }
            purchasedGoodsObj.put(addOrOutGoodsNumBo.getCode(), goodsBo);
        }
        customerMain.setPurchasedGoodsObj(purchasedGoodsObj);
        return customerMain;
    }

    private List<CustomerMain> jsonToObject(List<CustomerMain> customerMainList){
        for (CustomerMain customerMain:customerMainList){
            if (customerMain!=null){
                Map<Integer,CustomerConsumedStoresBo> storesBoMap=(new HashMap<Integer,CustomerConsumedStoresBo>(JSONObject.parseObject(customerMain.getConsumedStoresStr(), Map.class)));
                Map<String,CustomerPurchasedGoodsBo> goodsBoMap=(new HashMap<String,CustomerPurchasedGoodsBo>(JSONObject.parseObject(customerMain.getPurchasedGoodsStr(), Map.class)));
                for (Map.Entry<Integer,CustomerConsumedStoresBo> entry:storesBoMap.entrySet()){
                    CustomerConsumedStoresBo storesBo=JSONObject.parseObject(JSONObject.toJSONString(entry.getValue()),CustomerConsumedStoresBo.class);
                    storesBoMap.put(entry.getKey(),storesBo);
                }
                for (Map.Entry<String,CustomerPurchasedGoodsBo> entry:goodsBoMap.entrySet()){
                    CustomerPurchasedGoodsBo goodsBo=JSONObject.parseObject(JSONObject.toJSONString(entry.getValue()),CustomerPurchasedGoodsBo.class);
                    goodsBoMap.put(entry.getKey(),goodsBo);
                }
                customerMain.setConsumedStoresObj(storesBoMap);
                customerMain.setPurchasedGoodsObj(goodsBoMap);
            }
        }
        return customerMainList;
    }

}
